﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using UiUtility;
using VFTray.Config;

namespace VFTray
{
	public partial class WndConfigVision : Form
	{
		internal FeedTray Feed;

		private SwitchButtonWindows switchBtnWnds = new SwitchButtonWindows();
		internal WndVisoinSetting wndVS1 = new WndVisoinSetting();
		internal WndVisoinSetting wndVS2 = new WndVisoinSetting();
		public WndConfigVision()
		{
			InitializeComponent();
			TopLevel = false;
			FormClosing += (s, e) =>
			  {
				  switchBtnWnds.Close();
			  };

			switchBtnWnds.ButtonSize = new Size(60, 27);
			switchBtnWnds.Add(new Form[] { wndVS1, wndVS2 },
			   new string[] { "标识1", "标识2" },
			   new int[] { 20, 20 },
			   tableLayoutPanel4, flowLayoutPanel3);
			//tableLayoutPanel4.BackColor = Color.MediumAquamarine;
			switchBtnWnds.UpdateAuth(GlobalParams.Auth);
			switchBtnWnds.ShowWnd(0);


			foreach (DataGridViewColumn col in dataGridViewMove.Columns) col.SortMode = DataGridViewColumnSortMode.NotSortable;

			wndPicture1.OnDrawOnBufferedGraphics += wndPicture_OnDrawOnBufferedGraphics;
			wndPicture1.OnDrawOnPaintGraphics += wndPicture_OnDrawOnPaintGraphics;
			wndPicture1.EMouseMove += wndPicture_MouseMove;
			wndPicture1.OnSelectRect += WndPicture1_OnSelectRect;
			wndPicture1.EMouseClicked += wndPicture_MouseClicked;

			init_grid_move();

			VisibleChanged += (s, e) =>
			  {
				  if (Visible == false)
				  {
					  ParentHide();
					  wndVS1.ParentHide();
					  wndVS2.ParentHide();
					  return;
				  }

				  switchBtnWnds.UpdateAuth(GlobalParams.Auth);

				  if (Feed == null) return;

				  init_DatagridviewMove();

				  UpdateLights();

				  var bc = Feed.GetStep().boxparams;
				  binWorkSetting1.Freq = bc.Freq;
				  binWorkSetting1.Volt = bc.Volt;
				  binWorkSetting1.Times = bc.Times;
				  binWorkSetting1.RestAfter = bc.RestAfter;
				  binWorkSetting1.TryCountBin = bc.TryCountBin;
				  binWorkSetting1.TryCountShake = bc.TryCountShake;

				  snapRequestMode1.comboBoxMode.SelectedIndex = Feed.GetStep().req_mode;

				  coordinateControl1.Data2UI(Feed.GetCalibrationPts());

				  if (Feed.Cam.Connected) textBoxExposure.Text = Feed.Cam.Exposure.ToString("F0");
			  };

			coordinateControl1.TeachClicked += On_TeachClicked;

			checkBoxCrossLine.CheckedChanged += (s, e) => wndPicture1.Invalidate();
			ftLightOperations1.Buttons_Clicked += LightOps_ButtonClicked;

			buttonExposure.Click += (s, e) =>
			{
				if (Feed == null) return;
				if (Feed.Cam.Connected == false) return;
				try
				{
					int ex = Convert.ToInt32(textBoxExposure.Text);
					if (ex > Feed.Cam.ExposureMax || ex < Feed.Cam.ExposureMin)
					{
						MessageBox.Show(this, "曝光值取值范围 [" + Feed.Cam.ExposureMin.ToString("F0") + "," + Feed.Cam.ExposureMax.ToString("F0") + "]");
						return;
					}
					Feed.Cam.Exposure = ex;
					textBoxExposure.Text = Feed.Cam.Exposure.ToString("F0");
				}
				catch (Exception ex)
				{
					MessageBox.Show(this, "曝光设置错误" + Environment.NewLine + ex.Message, "ERROR");
				}
			};

			wndVS1.roiPanel1.BoxSelectionClick += (s, e) =>
			  {
				  _index_boxselection = 0;
				  wndPicture1.MouseSelecting = true;
			  };

			wndVS2.roiPanel1.BoxSelectionClick += (s, e) =>
			{
				_index_boxselection = 2;
				wndPicture1.MouseSelecting = true;
			};

			wndVS1.boxSelectMark1.ButtonClicked += (s, e) =>
			{
				Button btn = s as Button;
				int tag = Convert.ToInt32(btn.Tag);
				if (tag == 0)//boxselect
				{
					if (wndPicture1.Image == null) return;
					_index_boxselection = 1;
					wndPicture1.MouseSelecting = true;
				}
				else if (tag == 1)//test
				{
					wndPicture1.MouseSelecting = false;
					if (wndPicture1.Image == null)
					{
						MessageBox.Show(this, "未打开图片", "ERROR");
						return;
					}

					if (wndVS1.boxSelectMark1.Image == null)
					{
						MessageBox.Show(this, "未打开模板", "ERROR");
						return;
					}

					var vp = Feed.GetVision(0);

					Feed.CV.SetCalibrationPts(Feed.GetCalibrationPts());
					Feed.CV.SetBackParams(vp.method, vp.binm, vp.binp);
					Image img = wndVS1.boxSelectMark1.Image;
					Feed.CV.SetBackMarkWH(img.Width, img.Height);

					var pdata = FunHelper.ImageDataRevers(img);
					Feed.CV.SetBackMark(pdata);

					Feed.CV.SetImageWHCh(wndPicture1.Image.Width, wndPicture1.Image.Height, 1);
					Feed.CV.SetFlip(-2, 0);
					Feed.CV.SetROI(vp.roi_x, vp.roi_y, vp.roi_w, vp.roi_h);

					var pimage = FunHelper.ImageDataRevers(wndPicture1.Image);
					Feed.CV.SetImageBack(pimage);
					strResult = "图像处理中...";
					wndPicture1.Invalidate();

					Task.Run(() =>
					{
						try
						{
							if (vp.method == 0 || vp.method == 1)
							{
								Feed.CV.ProcessBackMark(vp.method);
								if (Feed.CV.ProcessBack(vp.method, vp.tolerancePer, -1) > 0)
								{
									Feed.CV.GetResultItem(0);
								}
							}
							else if (vp.method == 2)
							{
								string di = Path.Combine(GlobalParams.CD.ImagesPathO, Feed != null ? Feed.GetCfgFeed().cfgCamera.Name : "Cam");
								Feed.CV.SetYamlPath(di);
								Feed.CV.SetTemplateParam(vp.method, vp.matchParam.num_features,
									vp.matchParam.degree_begin, vp.matchParam.degree_end, vp.matchParam.step_degree,
									vp.matchParam.pyramid, vp.matchParam.weak_threshold, vp.matchParam.strong_threshold);

								Feed.CV.processMatch(vp.method, vp.matchParam.similarity, vp.matchParam.requireCount, vp.focusX, vp.focusY);
								Feed.CV.GetMatchData(0);
							}
							strResult = Feed.CV.GetResultString();
							Invoke(new Action(() =>
							{
								wndPicture1.Invalidate();
							}));
						}
						catch (Exception ex)
						{
							MessageBox.Show(this, "BoxSelectMark1.Clicked" + Environment.NewLine + ex.Message, "ERROR");
						}
						finally
						{
							Feed.InitCv();
						}
					});
				}
			};

			wndVS2.boxSelectMark1.ButtonClicked += (s, e) =>
			{

				Button btn = s as Button;
				int tag = Convert.ToInt32(btn.Tag);
				if (tag == 0)//boxselect
				{
					if (wndPicture1.Image == null) return;
					_index_boxselection = 3;
					wndPicture1.MouseSelecting = true;
				}
				else if (tag == 1)//test
				{
					wndPicture1.MouseSelecting = false;

					if (wndPicture1.Image == null)
					{
						MessageBox.Show(this, "未打开图片", "ERROR");
						return;
					}
					if (wndVS2.boxSelectMark1.Image == null)
					{
						MessageBox.Show(this, "未打开模板", "ERROR");
						return;
					}

					var vp = Feed.GetVision(1);
					Feed.CV.SetCalibrationPts(Feed.GetCalibrationPts());
					Feed.CV.SetBackParams(vp.method, vp.binm, vp.binp);
					Image img = wndVS2.boxSelectMark1.Image;
					Feed.CV.SetBackMarkWH(img.Width, img.Height);

					var pdata = FunHelper.ImageDataRevers(img);
					Feed.CV.SetBackMark(pdata);

					Feed.CV.SetImageWHCh(wndPicture1.Image.Width, wndPicture1.Image.Height, 1);
					Feed.CV.SetFlip(-2, 0);
					Feed.CV.SetROI(vp.roi_x, vp.roi_y, vp.roi_w, vp.roi_h);

					var pimage = FunHelper.ImageDataRevers(wndPicture1.Image);
					Feed.CV.SetImageBack(pimage);
					strResult = "图像处理中...";
					wndPicture1.Invalidate();
					Task.Run(() =>
					{
						try
						{
							if (vp.method == 0 || vp.method == 1)
							{
								Feed.CV.ProcessBackMark(vp.method);
								if (Feed.CV.ProcessBack(vp.method, vp.tolerancePer) > 0)
								{
									Feed.CV.GetResultItem(1);
								}
							}
							else if (vp.method == 2)
							{
								string di = Path.Combine(GlobalParams.CD.ImagesPathO, Feed != null ? Feed.GetCfgFeed().cfgCamera.Name : "Cam");
								Feed.CV.SetYamlPath(di);
								Feed.CV.SetTemplateParam(vp.method, vp.matchParam.num_features,
									vp.matchParam.degree_begin, vp.matchParam.degree_end, vp.matchParam.step_degree,
									vp.matchParam.pyramid, vp.matchParam.weak_threshold, vp.matchParam.strong_threshold);

								Feed.CV.processMatch(vp.method, vp.matchParam.similarity, vp.matchParam.requireCount, vp.focusX, vp.focusY);
								Feed.CV.GetMatchData(1);
							}
							strResult = Feed.CV.GetResultString();
							Invoke(new Action(() =>
							{
								wndPicture1.Invalidate();
							}));
						}
						catch (Exception ex)
						{
							MessageBox.Show(this, "BoxSelectMark1.Clicked" + Environment.NewLine + ex.Message, "ERROR");
						}
						finally
						{
							Feed.InitCv();
						}
					});
				}

			};
		}

		internal void Init()
		{
			wndVS1.Init(Feed, 0);
			wndVS2.Init(Feed, 1);
		}

		internal void ParentHide()
		{
			_index_teach = -1;
			wndPicture1.MouseSelecting = false;
			_index_boxselection = -1;
			if (Feed != null && Feed.Connected && Feed.Cam.Connected)
			{
				Feed.Cam.SetTriggerModeCont();
				Feed.Cam.TriggerEnabled(true);
				return;
			}
		}

		private int _index_boxselection = -1;//0 selet roi; 1 select mark


		#region light_ops

		private void LightOps_ButtonClicked(object sender, EventArgs e)
		{
			if (Feed == null || Feed.Connected == false) return;

			Button btn = sender as Button;
			int tag = Convert.ToInt32(btn.Tag);
			if (tag == 0)
			{
				if (ftLightOperations1.ALighting) Feed.LightSwitch(true, false);
				else Feed.LightSwitch(true, true);
			}
			else if (tag == 1)
			{
				if (ftLightOperations1.BLighting) Feed.LightSwitch(false, false);
				else Feed.LightSwitch(false, true);

				UpdateLights();
			}
			else if (tag == 2)
			{
				try
				{
					Feed.ReadLightMaxes();

					ushort uv = ftLightOperations1.BrightnessA;
					Feed.BrightnessPercent(true, uv);
					//uv = Convert.ToUInt16((Feed.LightMaxes[0] - 6) * 0.01F * uv + 6);

					//if (uv < 6 || uv > Feed.LightMaxes[0])
					//{
					//	MessageBox.Show($"亮度范围[6, {Feed.LightMaxes[0]}]", "Error");
					//	return;
					//}

					//Feed.Brightness(true, uv);
					UpdateLights();
				}
				catch (Exception ex)
				{
					MessageBox.Show(ex.Message, "ERROR");
				}
			}
			else if (tag == 3)
			{
				try
				{
					Feed.ReadLightMaxes();

					ushort uv = ftLightOperations1.BrightnessB;
					Feed.BrightnessPercent(false, uv);
					//uv = Convert.ToUInt16((Feed.LightMaxes[1] - 6) * 0.01F * uv + 6);
					//if (uv < 6 || uv > Feed.LightMaxes[1])
					//{
					//	MessageBox.Show($"亮度范围[6, {Feed.LightMaxes[0]}]", "Error");
					//	return;
					//}

					//Feed.Brightness(false, uv);
					UpdateLights();
				}
				catch (Exception ex)
				{
					MessageBox.Show(ex.Message, "ERROR");
				}
			}
		}
		private void UpdateLights()
		{
			if (Feed == null || Feed.Connected == false) return;

			if (Feed.ReadLightMaxes())
			{
				//ftLightOperations1.LabelA = $"亮度A(6,{Feed.LightMaxes[0]})";
				//ftLightOperations1.LabelA = $"亮度B(6,{Feed.LightMaxes[1]})";
			}

			if (Feed.ReadLightValues())
			{
				ushort pa = Convert.ToUInt16(100F * (Feed.LightValues[0] - 6.0F) / (Feed.LightMaxes[0] - 6.0F));
				ushort pb = Convert.ToUInt16(100F * (Feed.LightValues[1] - 6.0F) / (Feed.LightMaxes[1] - 6.0F));

				ftLightOperations1.BrightnessA = pa;
				ftLightOperations1.BrightnessB = pb;
				//ftLightOperations1.BrightnessA = Feed.LightValues[0];
				//ftLightOperations1.BrightnessB = Feed.LightValues[1];
			}
		}

		#endregion light_ops

		#region steps

		#region moves
		private void init_grid_move()
		{
			MoveColumn1.DisplayMember = "Item2";
			MoveColumn1.ValueMember = "Item1";

			MoveColumn1.DataSource = new List<Tuple<int, string>>
				{
					new Tuple<int, string>(0,"上"),
					new Tuple<int, string>(1,"下"),
					new Tuple<int, string>(2, "左"),
					new Tuple<int, string>(3, "右"),
					new Tuple<int, string>(4, "左上"),
					new Tuple<int, string>(5, "右上"),
					new Tuple<int, string>(6, "左下"),
					//new Tuple<int, string>(7, "聚拢"),
					new Tuple<int, string>(8, "右下"),
					new Tuple<int, string>(9, "垂直居中"),
					new Tuple<int, string>(10, "水平居中"),
					new Tuple<int, string>(11, "振散"),
					new Tuple<int, string>(12, "翻面"),
					//new Tuple<int, string>(0, "组合2"),
					//new Tuple<int, string>(0, "组合1")
				};


			dataGridViewMove.EditingControlShowing += DataGridViewMove_EditingControlShowing;
			dataGridViewMove.CellValidating += DataGridViewMove_CellValidating;
			dataGridViewMove.CellValidated += DataGridViewMove_CellValidated;

			addToolStripMenuItem.Click += Move_AddToolStripMenuItem_Click;
			removeToolStripMenuItem.Click += Move_RemoveToolStripMenuItem_Click;
		}
		private void init_DatagridviewMove()
		{
			try
			{
				dataGridViewMove.Rows.Clear();
				var steps = Feed.GetStep();
				foreach (var s in steps.moves)
				{
					int index = dataGridViewMove.Rows.Add();
					var row = dataGridViewMove.Rows[index];
					row.Cells[0].Value = (int)s.Mode;
					row.Cells[1].Value = (s.Times * 0.001F);
					row.Cells[2].Value = (s.Freq * 0.1F);
					row.Cells[3].Value = (s.Volt * 0.1F);
					row.Cells[4].Value = (s.RestAfter * 0.001F);
				}
			}
			catch (Exception ex)
			{
				MessageBox.Show(ex.Message, "ERROR");
			}
		}

		private void saveDataMove()
		{
			var step = Feed.GetStep();
			step.moves.Clear();
			var steps = step.moves;
			foreach (DataGridViewRow row in dataGridViewMove.Rows)
			{
				try
				{
					ushort mode = Convert.ToUInt16(row.Cells[0].Value);
					int time = Convert.ToInt32(Convert.ToSingle(row.Cells[1].Value) * 1000);
					ushort freq = Convert.ToUInt16(Convert.ToSingle(row.Cells[2].Value) * 10);
					ushort volt = Convert.ToUInt16(Convert.ToSingle(row.Cells[3].Value) * 10);
					int restafter = Convert.ToUInt16(Convert.ToSingle(row.Cells[4].Value) * 1000);
					var s = new Config.PShakeMove() { Mode = mode, Times = time, Freq = freq, Volt = volt, RestAfter = restafter };
					steps.Add(s);
				}
				catch (Exception ex)
				{
					System.Diagnostics.Debug.WriteLine(ex.Message);
				}
			}
		}

		#region context_menu_move
		private void Move_RemoveToolStripMenuItem_Click(object sender, EventArgs e)
		{
			if (dataGridViewMove.CurrentRow == null) return;
			var cr = dataGridViewMove.CurrentRow.Index;
			dataGridViewMove.Rows.RemoveAt(cr);
		}

		private void Move_AddToolStripMenuItem_Click(object sender, EventArgs e)
		{
			int index = dataGridViewMove.Rows.Add();
			var row = dataGridViewMove.Rows[index];
			var s = new Config.PShakeMove();
			row.Cells[0].Value = (int)s.Mode;
			row.Cells[1].Value = (s.Times * 0.001F);
			row.Cells[2].Value = (s.Freq * 0.1F);
			row.Cells[3].Value = (s.Volt * 0.1F);
		}
		#endregion context_menu_move

		#region data_validation_snap
		private void DataGridViewMove_CellValidated(object sender, DataGridViewCellEventArgs e)
		{
			if (e.ColumnIndex != 0)
			{
				try
				{
					var cell = dataGridViewMove.CurrentCell;
					string s = cell.FormattedValue.ToString();
					float fv = Convert.ToSingle(s);
					cell.Value = fv;
				}
				catch (Exception ex)
				{
					System.Diagnostics.Debug.WriteLine(ex.Message);
				}
			}
		}

		private void DataGridViewMove_CellValidating(object sender, DataGridViewCellValidatingEventArgs e)
		{
			string s = e.FormattedValue.ToString();
			if (e.ColumnIndex == 1)
			{
				try
				{
					float fv = Convert.ToSingle(s);
					if (fv < 0.1F || fv > 20.0F)
					{
						e.Cancel = true;
						MessageBox.Show("请输入正确数据" + Environment.NewLine + MoveColumn2.HeaderText, "数值超范围");
					}
				}
				catch (Exception ex)
				{
					e.Cancel = true;
					MessageBox.Show("请输入正确数据" + Environment.NewLine + MoveColumn2.HeaderText + Environment.NewLine + ex.Message, "格式错误");
				}
			}
			else if (e.ColumnIndex == 2)
			{
				try
				{
					float fv = Convert.ToSingle(s);
					if (fv < 10.0F || fv > 200.0F)
					{
						e.Cancel = true;
						MessageBox.Show("请输入正确数据" + Environment.NewLine + MoveColumn3.HeaderText, "数值超范围");
					}
				}
				catch (Exception ex)
				{
					e.Cancel = true;
					MessageBox.Show("请输入正确数据" + Environment.NewLine + MoveColumn3.HeaderText + Environment.NewLine + ex.Message, "格式错误");
				}
			}
			else if (e.ColumnIndex == 2)
			{
				try
				{
					float fv = Convert.ToSingle(s);
					if (fv < 0.0F || fv > 24.0F)
					{
						e.Cancel = true;
						MessageBox.Show("请输入正确数据" + Environment.NewLine + MoveColumn4.HeaderText, "数值超范围");
					}
				}
				catch (Exception ex)
				{
					e.Cancel = true;
					MessageBox.Show("请输入正确数据" + Environment.NewLine + MoveColumn4.HeaderText + Environment.NewLine + ex.Message, "格式错误");
				}
			}
		}

		private void DataGridViewMove_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
		{
			if (e.Control is DataGridViewTextBoxEditingControl DGV_textBox)
			{
				DGV_textBox.KeyPress += Move_textBox_KeyPress;
			}
		}
		char[] chs_plus_allow = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.', (char)8 };
		private void Move_textBox_KeyPress(object sender, KeyPressEventArgs e)
		{
			if (chs_plus_allow.Contains(e.KeyChar))
			{
				e.Handled = false;
			}
			else
				e.Handled = true;
		}
		#endregion data_validation_snap

		#endregion moves

		#endregion steps

		#region onsize_layout
		protected override void OnSizeChanged(EventArgs e)
		{
			base.OnSizeChanged(e);
			wndPicture1.ImageCenter();
		}

		protected override void OnLayout(LayoutEventArgs levent)
		{
			base.OnLayout(levent);
			wndPicture1.ImageCenter();
		}
		#endregion onsize_layout


		internal void SetPicture(Bitmap mBitmap)
		{
			strTime = DateTime.Now.ToString("HH:mm:ss fff");
			Invoke(new Action(() => wndPicture1.Image = mBitmap));
		}
		private string strTime = "";
		private string strResult = "CV Ready";
		private void wndPicture_OnDrawOnPaintGraphics(Graphics g, float alpha, RectangleF rectImg)
		{
			if (Feed == null) return;

			g.DrawString(Feed.GetCfgFeed().cfgCamera.Name + " " + strTime, Font, Brushes.GhostWhite, 50, 50);
			if (strResult == "CV Ready") g.DrawString(strResult, Font, Brushes.GhostWhite, 50, 70);
			if (strResult == "NO Objects") g.DrawString(strResult, Font, Brushes.Red, 50, 70);
			else g.DrawString(strResult, Font, Brushes.Blue, 50, 70);

		}

		private RectangleF GetROI()
		{
			if (wndVS1.Visible)
				return new RectangleF(wndVS1.roiPanel1.X, wndVS1.roiPanel1.Y, wndVS1.roiPanel1.W, wndVS1.roiPanel1.H);
			else return new RectangleF(wndVS2.roiPanel1.X, wndVS2.roiPanel1.Y, wndVS2.roiPanel1.W, wndVS2.roiPanel1.H);
		}

		private PVisionParam GetVision()
		{
			if (wndVS1.Visible) return Feed.GetStep().vision1;
			return Feed.GetStep().vision2;
		}
		private void wndPicture_OnDrawOnBufferedGraphics(Graphics g, float alpha, RectangleF rectImg)
		{
			DrawHelper.DrawImageRect(g, alpha, rectImg, Pens.White);
			if (checkBoxCrossLine.Checked)
			{
				DrawHelper.DrawCenterCross(g, alpha, rectImg, Pens.Yellow);
			}
			if (wndPicture1.Image == null) return;
			if (Feed == null) return;

			DrawHelper.DrawROI(g, alpha, rectImg, GetROI(), Color.BlueViolet, Font);
			var cp = GetVision();

			lock (Feed.CV)
			{
				GlobalParams.MF.wndRun.drawCVResult(g, alpha, rectImg, Feed.CV.ResultData);
			}

			try
			{
				var ps = textBoxCoord.Text.Split(new char[] { ',' });
				int x = 0;
				int y = 0;
				if (int.TryParse(ps[0], out x) && int.TryParse(ps[1], out y))
				{
					PointF pt1 = new PointF();
					pt1.X = x * alpha + rectImg.X;
					pt1.Y = y * alpha + rectImg.Y;
					g.DrawLine(Pens.DarkGreen, pt1.X + 10 * alpha, pt1.Y, pt1.X - 10 * alpha, pt1.Y);
					g.DrawLine(Pens.DarkGreen, pt1.X, pt1.Y + 10 * alpha, pt1.X, pt1.Y - 10 * alpha);
				}
			}
			catch (Exception ex)
			{
				System.Diagnostics.Debug.WriteLine(ex.Message);
			}
		}

		private void wndPicture_MouseClicked(PointF pt, float alpha, RectangleF rectImg)
		{
			if (wndPicture1.Image == null) return;

			int x = (int)pt.X;
			int y = (int)pt.Y;
			textBoxCoord.Text = x.ToString() + "," + y.ToString();
			wndPicture1.Invalidate();
		}

		private void wndPicture_MouseMove(PointF pt, float alpha, RectangleF rectImg)
		{
			lock (wndPicture1.Image)
			{
				Bitmap bmp = (Bitmap)wndPicture1.Image;


				//PointF pt = wndPicture1.PointMouseMove;
				int x = (int)pt.X;
				int y = (int)pt.Y;
				if (x >= 0 && x < bmp.Width && y >= 0 && y < bmp.Height)
				{
					Color color = bmp.GetPixel(x, y);
					labelGray.Text = string.Format("Gray = {0}  Pixel Coord. = [{1}, {2}]", color.R, x, y);
				}
			}
		}

		private void WndPicture1_OnSelectRect(PointF pt1, PointF pt2)
		{
			wndPicture1.MouseSelecting = false;
			Bitmap bmp = wndPicture1.Image as Bitmap;
			if (bmp == null) return;

			int x1 = Math.Max(0, (int)Math.Min(pt1.X, pt2.X));
			int y1 = Math.Max(0, (int)Math.Min(pt1.Y, pt2.Y));
			int x2 = Math.Min(bmp.Width, (int)Math.Max(pt1.X, pt2.X));
			int y2 = Math.Min(bmp.Height, (int)Math.Max(pt1.Y, pt2.Y));

			if (_index_boxselection == 0)
			{
				wndVS1.roiPanel1.X = x1;
				wndVS1.roiPanel1.Y = y1;
				wndVS1.roiPanel1.W = x2 - x1;
				wndVS1.roiPanel1.H = y2 - y1;
			}
			else if (_index_boxselection == 1)
			{
				var mark = FunHelper.Crop(bmp, new Rectangle(x1, y1, x2 - x1, y2 - y1));
				wndVS1.boxSelectMark1.SetSelectedMark(mark, "Video Picture");
			}
			else if (_index_boxselection == 2)
			{
				wndVS2.roiPanel1.X = x1;
				wndVS2.roiPanel1.Y = y1;
				wndVS2.roiPanel1.W = x2 - x1;
				wndVS2.roiPanel1.H = y2 - y1;
			}
			else if (_index_boxselection == 3)
			{
				var mark = FunHelper.Crop(bmp, new Rectangle(x1, y1, x2 - x1, y2 - y1));
				wndVS2.boxSelectMark1.SetSelectedMark(mark, "Video Picture");
			}
		}


		internal void OnUiTimer()
		{
			if (!Visible) return;
			if (Feed == null) return;
			if (Feed.Connected)
			{
				if (Feed.S_LightA != ftLightOperations1.ALighting) ftLightOperations1.ALighting = Feed.S_LightA;
				if (Feed.S_LightB != ftLightOperations1.BLighting) ftLightOperations1.BLighting = Feed.S_LightB;
			}
			else
			{
				if (ftLightOperations1.ALighting) ftLightOperations1.ALighting = false;
				if (ftLightOperations1.BLighting) ftLightOperations1.BLighting = false;
			}

			var cam = Feed.Cam;
			if (cam != null && cam.Connected && cam.IsStreamed && cam.mBitmap != null)
			{
				strTime = "Stream";
				wndPicture1.Image = cam.mBitmap;
			}
			if (cam != null && cam.Connected)
			{
				buttonStream.BackColor = cam.IsStreamed ? Color.Green : SystemColors.Control;
			}
			else
			{
				buttonStream.BackColor = SystemColors.Control;
			}

			wndVS1.roiPanel1.BoxCheckEnable = (wndPicture1.Image != null);
			wndVS2.roiPanel1.BoxCheckEnable = (wndPicture1.Image != null);
			//buttonSnap.Enabled = !GlobalParams.PC.PP.bAutoRuning;
		}

		private void buttonOpenPic_Click(object sender, EventArgs e)
		{
			OpenFileDialog dlg = new OpenFileDialog();
			dlg.Filter = "Image File(*.jpg,*.bmp,*.png)|*.jpg;*.bmp;*.png|All file(*.*)|*.*";

			string di = Path.Combine(GlobalParams.CD.ImagesPathO, Feed != null ? Feed.GetCfgFeed().cfgCamera.Name : "Cam");
			if (Directory.Exists(di) == false) Directory.CreateDirectory(di);

			dlg.InitialDirectory = di;
			dlg.Multiselect = false;
			dlg.CheckPathExists = true;
			dlg.CheckFileExists = true;

			if (dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK)
			{
				var img = ImageUtility.ImageHelper.From(dlg.FileName);
				if (img.PixelFormat == System.Drawing.Imaging.PixelFormat.Format24bppRgb) img = ImageUtility.ImageHelper.Bmp24To8((Bitmap)img);
				else if (img.PixelFormat == System.Drawing.Imaging.PixelFormat.Format32bppArgb) img = ImageUtility.ImageHelper.Bmp32To8((Bitmap)img);

				wndPicture1.Image = img;
				wndPicture1.ImageCenter();
			}
		}

		private void buttonSavePic_Click(object sender, EventArgs e)
		{
			if (wndPicture1.Image == null) return;

			SaveFileDialog dlg = new SaveFileDialog();
			dlg.Filter = "Bitmap File(*.bmp)|*.bmp|All file(*.*)|*.*";
			dlg.FilterIndex = 0;
			dlg.DefaultExt = "bmp";

			dlg.FileName = DateTime.Now.ToString("yyyyMMdd_HHmmss");
			dlg.AddExtension = true;

			string di = Path.Combine(GlobalParams.CD.ImagesPathO, Feed != null ? Feed.GetCfgFeed().cfgCamera.Name : "Cam");
			if (Directory.Exists(di) == false) Directory.CreateDirectory(di);

			dlg.InitialDirectory = di;
			dlg.RestoreDirectory = true;
			dlg.OverwritePrompt = true;
			dlg.Title = "Save Picture";
			if (dlg.ShowDialog() == DialogResult.OK) wndPicture1.Image.Save(dlg.FileName);
		}

		private void buttonSnap_Click(object sender, EventArgs e)
		{
			if (Feed == null) return;
			if (Feed.Cam.Connected == false) return;
			Feed.Cam.TriggerEnabled(true);
			Feed.Cam.SetTriggerModeSoft();
			Feed.Cam.Trigger();
		}

		private void buttonStream_Click(object sender, EventArgs e)
		{
			if (Feed == null) return;
			if (Feed.Cam.Connected == false) return;
			if (Feed.Cam.IsStreamed)
			{
				Feed.Cam.TriggerEnabled(true);
				Feed.Cam.SetTriggerModeSoft();
			}
			else
			{
				Feed.Cam.SetTriggerModeCont();
				Feed.Cam.TriggerEnabled(false);
			}
		}

		private void checkBoxCrossline_CheckedChanged(object sender, EventArgs e)
		{
			wndPicture1.Invalidate();
		}

		private void buttonSave_Click(object sender, EventArgs e)
		{
			if (MessageBox.Show(this, "请确认，是否保存当前运行步骤？", "确认", MessageBoxButtons.YesNo, MessageBoxIcon.Question) != DialogResult.Yes)
			{
				return;
			}
			if (wndVS1.UI2Data() == false) return;
			if (wndVS2.UI2Data() == false) return;

			saveDataMove();
			try
			{

				if (binWorkSetting1.UI2Data())
				{
					var cfg = Feed.GetStep().boxparams;
					cfg.Freq = binWorkSetting1.Freq;
					cfg.Volt = binWorkSetting1.Volt;
					cfg.Times = binWorkSetting1.Times;
					cfg.RestAfter = binWorkSetting1.RestAfter;
					cfg.TryCountBin = binWorkSetting1.TryCountBin;
					cfg.TryCountShake = binWorkSetting1.TryCountShake;
					Feed.GetStep().req_mode = snapRequestMode1.comboBoxMode.SelectedIndex;

				}


			}
			catch (Exception ex)
			{
				MessageBox.Show(ex.Message, "Error");
			}

			GlobalParams.CRF.Save();

			List<float> calib_xyuv = new List<float>();
			if (coordinateControl1.UI2Data(calib_xyuv)) Feed.SetCalibrationTuple(calib_xyuv);
			GlobalParams.CDF.Save();
			Feed.InitCv();

			init_DatagridviewMove();

			var bc = Feed.GetStep().boxparams;
			binWorkSetting1.Freq = bc.Freq;
			binWorkSetting1.Volt = bc.Volt;
			binWorkSetting1.Times = bc.Times;
			binWorkSetting1.RestAfter = bc.RestAfter;

			wndPicture1.Invalidate();
		}

		private void buttonTestMoving_Click(object sender, EventArgs e)
		{
			if (Feed != null && Feed.Connected)
			{
				if (Feed.msShakeing.LO)
				{
					Feed.ShakeNeedResp = false;
					Feed.BiningNeedResp = false;
					Feed.AllInOne = false;
					Feed.CountShake = 0;
					Feed.CountBin = 0;
					Feed.Index_Mark1 = 0;
					Feed.Index_Mark2 = 0;
					Feed.CountRequired1 = 0;
					Feed.CountRequired2 = 0;
					Feed.StartShakeing();
				}
			}
		}
		
		private void buttonManulFeeder_Click(object sender, EventArgs e)
		{
			var dlg = new DlgManualTray();
			dlg.Feed = Feed;
			dlg.ShowDialog(this);
		}


		private int _index_teach = -1;
		private void On_TeachClicked(object sender, bool xy_uv)
		{
			Button btn = sender as Button;
			try
			{
				int idx = Convert.ToInt32(btn.Tag);
				_index_teach = idx;
				if (xy_uv)
				{
					var rv = GlobalParams.CS.rvConfig;
					rv.SiteID = Feed.ID;
					string txt = GlobalParams.CS.rvConfig.NewCommand("Axes=?");
					GlobalParams.CS.Send(txt);
				}
				else
				{
					var ps = textBoxCoord.Text.Split(new char[] { ',' });
					if (ps.Length < 2) return;
					float u = Convert.ToInt32(ps[0]);
					float v = Convert.ToInt32(ps[1]);
					coordinateControl1.SetUV(_index_teach, u, v);
					_index_teach = -1;
				}
			}
			catch (Exception ex)
			{
				_index_teach = -1;
				MessageBox.Show(ex.Message, "TEACH BUTTON ERROR");
			}
		}

		private void buttonGetAxis_Click(object sender, EventArgs e)
		{
			var rv = GlobalParams.CS.rvConfig;
			rv.SiteID = Feed.ID;
			string txt = GlobalParams.CS.rvConfig.NewCommand("Axes=?");
			GlobalParams.CS.Send(txt);
		}

		internal void NotifyAxesCoord(float x, float y)
		{

			Invoke(new Action(() =>
			{
				if (_index_teach < 0)
				{
					DlgAxesCoordinate dlg = new DlgAxesCoordinate();
					dlg.SetCoordinate(x, y);
					dlg.Show(this);
				}
				else
				{
					coordinateControl1.SetXY(_index_teach, x, y);
					_index_teach = -1;
				}
				
			}));
		}

	}
}
